using ThoughtWorks.CruiseControl.Core;
using ThoughtWorks.CruiseControl.Core.Publishers;
using ThoughtWorks.CruiseControl.Core.Publishers.Statistics;

namespace CCStatistics
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.IO;
    using System.Reflection;
    using System.Threading;
    using System.Windows.Forms;


    using CCStatistics.Domain.Api;
    using CCStatistics.Domain.Api.Interfaces;

    /// <summary>
    /// CCStatistics for CruiseControl.Net 1.3+. This statistics utility application by Grant Drake (http://www.kiwidude.com/blog/).
    /// Generates historical build statistics information for users upgrading to CruiseControl.Net 1.1. 
    /// 
    /// Updated by Damon W. Carr to support CruseControl.NET 1.3
    /// with major additional refactorings and enhanced capabilities
    /// 7/2007
    /// 
    /// You can leverage the API directly in CCStatticsApi however for now
    /// you need to also reference ThoughtWorks.CruiseControl.Core due to 
    /// type dependencies and non-contract based types required bt CruiseControl.
    /// 
    /// In a future release I plan on facading these so you can code to onlt the
    /// API reference.
    /// 
    /// Also, I hopoe to allow this utility to work when run from a browser which
    /// connects to the main CC ControlPanel so no access is required to the build server
    /// directly (via say terminal services or physical location)
    /// 
    /// By default only "new" builds after upgrading will have statistics generated. 
    /// This tool allows a team to simulate having CC.Net 1.1 statistics functionality in place
    /// for the complete history of build log files available.
    /// </summary>
    public class MainForm : Form, ICCStatsView
    {
        private const int SB_LINEDOWN = 1;

        private const int WM_VSCROLL = 0x115;

        private IProjectList _projects;

        #region Designer Variables

        private Button btnRecalculateStatistics;

        private Button button1;

        private CheckBox chkDetailedProgress;

        private IContainer components;

        private OpenFileDialog dlgCCNetOPenConfig;

        private GroupBox groupBox1;

        private GroupBox grpDetails;

        private ImageList imgTreeNodes;

        private Label lblCCNetConfigPath;

        private Label lblOpen;

        private Label lblProgress;

        private Label lblSelectProjects;

        private Label lblStats;

        private LinkLabel lnkExport;

        private CheckedListBox lstProjects;

        private MainMenu mainMenu;

        private MenuItem mnuFile;

        private MenuItem mnuFileExit;

        private MenuItem mnuHelp;

        private MenuItem mnuHelpAbout;

        private ProgressBar progressBar;

        private RichTextBox rtbOutput;

        private SaveFileDialog saveFileDialog1;

        private ToolTip tollTip;

        private TreeView treeStatistics;
        private Button btnSelectAll;
        private Button btnSelectNone;

        private TextBox txtCCNetPath;
        private bool _lastProjectWasAborted = false;

        #endregion Designer Variables

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="MainForm"/> class.
        /// </summary>
        public MainForm()
        {
            InitializeComponent();
        }

        #endregion Constructor

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            System.Windows.Forms.TreeNode treeNode1 = new System.Windows.Forms.TreeNode("Statistics");
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
            this.lblSelectProjects = new System.Windows.Forms.Label();
            this.lstProjects = new System.Windows.Forms.CheckedListBox();
            this.btnRecalculateStatistics = new System.Windows.Forms.Button();
            this.lblCCNetConfigPath = new System.Windows.Forms.Label();
            this.txtCCNetPath = new System.Windows.Forms.TextBox();
            this.rtbOutput = new System.Windows.Forms.RichTextBox();
            this.mainMenu = new System.Windows.Forms.MainMenu(this.components);
            this.mnuFile = new System.Windows.Forms.MenuItem();
            this.mnuFileExit = new System.Windows.Forms.MenuItem();
            this.mnuHelp = new System.Windows.Forms.MenuItem();
            this.mnuHelpAbout = new System.Windows.Forms.MenuItem();
            this.chkDetailedProgress = new System.Windows.Forms.CheckBox();
            this.lblProgress = new System.Windows.Forms.Label();
            this.dlgCCNetOPenConfig = new System.Windows.Forms.OpenFileDialog();
            this.lblStats = new System.Windows.Forms.Label();
            this.treeStatistics = new System.Windows.Forms.TreeView();
            this.imgTreeNodes = new System.Windows.Forms.ImageList(this.components);
            this.button1 = new System.Windows.Forms.Button();
            this.lblOpen = new System.Windows.Forms.Label();
            this.tollTip = new System.Windows.Forms.ToolTip(this.components);
            this.grpDetails = new System.Windows.Forms.GroupBox();
            this.lnkExport = new System.Windows.Forms.LinkLabel();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.btnSelectNone = new System.Windows.Forms.Button();
            this.btnSelectAll = new System.Windows.Forms.Button();
            this.progressBar = new System.Windows.Forms.ProgressBar();
            this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog();
            this.grpDetails.SuspendLayout();
            this.groupBox1.SuspendLayout();
            this.SuspendLayout();
            // 
            // lblSelectProjects
            // 
            this.lblSelectProjects.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.lblSelectProjects.ForeColor = System.Drawing.Color.Black;
            this.lblSelectProjects.Location = new System.Drawing.Point(31, 61);
            this.lblSelectProjects.Name = "lblSelectProjects";
            this.lblSelectProjects.Size = new System.Drawing.Size(75, 53);
            this.lblSelectProjects.TabIndex = 3;
            this.lblSelectProjects.Text = "&Select Projects";
            this.lblSelectProjects.TextAlign = System.Drawing.ContentAlignment.TopRight;
            // 
            // lstProjects
            // 
            this.lstProjects.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.lstProjects.CheckOnClick = true;
            this.lstProjects.Location = new System.Drawing.Point(112, 61);
            this.lstProjects.Name = "lstProjects";
            this.lstProjects.Size = new System.Drawing.Size(559, 68);
            this.lstProjects.TabIndex = 4;
            this.lstProjects.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.lstProjects_ItemCheck);
            // 
            // btnRecalculateStatistics
            // 
            this.btnRecalculateStatistics.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
            this.btnRecalculateStatistics.BackColor = System.Drawing.Color.SteelBlue;
            this.btnRecalculateStatistics.FlatAppearance.BorderColor = System.Drawing.Color.Black;
            this.btnRecalculateStatistics.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
            this.btnRecalculateStatistics.Font = new System.Drawing.Font("Verdana", 10F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.btnRecalculateStatistics.ForeColor = System.Drawing.Color.White;
            this.btnRecalculateStatistics.Location = new System.Drawing.Point(474, 165);
            this.btnRecalculateStatistics.Name = "btnRecalculateStatistics";
            this.btnRecalculateStatistics.Size = new System.Drawing.Size(197, 25);
            this.btnRecalculateStatistics.TabIndex = 5;
            this.btnRecalculateStatistics.Text = "&Recalculate Statistics";
            this.tollTip.SetToolTip(this.btnRecalculateStatistics, "Click here to recalculate statistics on the projects you jave selected ");
            this.btnRecalculateStatistics.UseVisualStyleBackColor = false;
            this.btnRecalculateStatistics.Click += new System.EventHandler(this._OnRecalculateStatisticsButtonClick);
            // 
            // lblCCNetConfigPath
            // 
            this.lblCCNetConfigPath.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.lblCCNetConfigPath.ForeColor = System.Drawing.Color.Black;
            this.lblCCNetConfigPath.Location = new System.Drawing.Point(8, 20);
            this.lblCCNetConfigPath.Name = "lblCCNetConfigPath";
            this.lblCCNetConfigPath.Size = new System.Drawing.Size(98, 20);
            this.lblCCNetConfigPath.TabIndex = 0;
            this.lblCCNetConfigPath.Text = "&CC Config";
            this.lblCCNetConfigPath.TextAlign = System.Drawing.ContentAlignment.TopRight;
            // 
            // txtCCNetPath
            // 
            this.txtCCNetPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.txtCCNetPath.Location = new System.Drawing.Point(112, 20);
            this.txtCCNetPath.Name = "txtCCNetPath";
            this.txtCCNetPath.Size = new System.Drawing.Size(559, 21);
            this.txtCCNetPath.TabIndex = 1;
            // 
            // rtbOutput
            // 
            this.rtbOutput.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.rtbOutput.Location = new System.Drawing.Point(112, 28);
            this.rtbOutput.Margin = new System.Windows.Forms.Padding(0);
            this.rtbOutput.Name = "rtbOutput";
            this.rtbOutput.Size = new System.Drawing.Size(559, 62);
            this.rtbOutput.TabIndex = 7;
            this.rtbOutput.Text = "";
            this.rtbOutput.TextChanged += new System.EventHandler(this.rtbOutput_TextChanged);
            // 
            // mainMenu
            // 
            this.mainMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mnuFile,
            this.mnuHelp});
            // 
            // mnuFile
            // 
            this.mnuFile.Index = 0;
            this.mnuFile.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mnuFileExit});
            this.mnuFile.Text = "&File";
            // 
            // mnuFileExit
            // 
            this.mnuFileExit.Index = 0;
            this.mnuFileExit.Text = "E&xit";
            this.mnuFileExit.Click += new System.EventHandler(this._OnFileExitMenuClick);
            // 
            // mnuHelp
            // 
            this.mnuHelp.Index = 1;
            this.mnuHelp.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mnuHelpAbout});
            this.mnuHelp.Text = "&Help";
            // 
            // mnuHelpAbout
            // 
            this.mnuHelpAbout.Index = 0;
            this.mnuHelpAbout.Text = "&About...";
            this.mnuHelpAbout.Click += new System.EventHandler(this._OnHelpAboutClick);
            // 
            // chkDetailedProgress
            // 
            this.chkDetailedProgress.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
            this.chkDetailedProgress.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
            this.chkDetailedProgress.Checked = true;
            this.chkDetailedProgress.CheckState = System.Windows.Forms.CheckState.Checked;
            this.chkDetailedProgress.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.chkDetailedProgress.ForeColor = System.Drawing.Color.Black;
            this.chkDetailedProgress.Location = new System.Drawing.Point(474, 135);
            this.chkDetailedProgress.Name = "chkDetailedProgress";
            this.chkDetailedProgress.Size = new System.Drawing.Size(197, 24);
            this.chkDetailedProgress.TabIndex = 8;
            this.chkDetailedProgress.Text = "Show details of progress";
            this.tollTip.SetToolTip(this.chkDetailedProgress, "This will either display the processing results or hide them (and by hiding them " +
                    "the processing will go faster)");
            this.chkDetailedProgress.CheckedChanged += new System.EventHandler(this.chkDetailedProgress_CheckedChanged);
            // 
            // lblProgress
            // 
            this.lblProgress.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.lblProgress.ForeColor = System.Drawing.Color.Black;
            this.lblProgress.Location = new System.Drawing.Point(31, 28);
            this.lblProgress.Name = "lblProgress";
            this.lblProgress.Size = new System.Drawing.Size(75, 20);
            this.lblProgress.TabIndex = 11;
            this.lblProgress.Text = "Pro&gress";
            this.lblProgress.TextAlign = System.Drawing.ContentAlignment.TopRight;
            // 
            // dlgCCNetOPenConfig
            // 
            this.dlgCCNetOPenConfig.DefaultExt = "config";
            this.dlgCCNetOPenConfig.FileName = "ccnet.config";
            this.dlgCCNetOPenConfig.Filter = ".config files|*.config";
            // 
            // lblStats
            // 
            this.lblStats.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
            this.lblStats.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.lblStats.ForeColor = System.Drawing.Color.Black;
            this.lblStats.Location = new System.Drawing.Point(28, 108);
            this.lblStats.Name = "lblStats";
            this.lblStats.Size = new System.Drawing.Size(78, 20);
            this.lblStats.TabIndex = 16;
            this.lblStats.Text = "Statistics";
            this.lblStats.TextAlign = System.Drawing.ContentAlignment.TopRight;
            this.lblStats.Click += new System.EventHandler(this.lblStats_Click);
            // 
            // treeStatistics
            // 
            this.treeStatistics.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.treeStatistics.ImageIndex = 1;
            this.treeStatistics.ImageList = this.imgTreeNodes;
            this.treeStatistics.Location = new System.Drawing.Point(112, 107);
            this.treeStatistics.Name = "treeStatistics";
            treeNode1.ImageIndex = 1;
            treeNode1.Name = "Node0";
            treeNode1.Text = "Statistics";
            this.treeStatistics.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
            treeNode1});
            this.treeStatistics.SelectedImageIndex = 0;
            this.treeStatistics.ShowLines = false;
            this.treeStatistics.ShowNodeToolTips = true;
            this.treeStatistics.ShowPlusMinus = false;
            this.treeStatistics.ShowRootLines = false;
            this.treeStatistics.Size = new System.Drawing.Size(559, 141);
            this.treeStatistics.TabIndex = 17;
            // 
            // imgTreeNodes
            // 
            this.imgTreeNodes.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imgTreeNodes.ImageStream")));
            this.imgTreeNodes.TransparentColor = System.Drawing.Color.Transparent;
            this.imgTreeNodes.Images.SetKeyName(0, "icon_openfold.gif");
            this.imgTreeNodes.Images.SetKeyName(1, "icon_haus.gif");
            // 
            // button1
            // 
            this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.button1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
            this.button1.BackColor = System.Drawing.Color.Transparent;
            this.button1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
            this.button1.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
            this.button1.Image = ((System.Drawing.Image)(resources.GetObject("button1.Image")));
            this.button1.Location = new System.Drawing.Point(687, 20);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(54, 50);
            this.button1.TabIndex = 18;
            this.tollTip.SetToolTip(this.button1, "Click here to open your CruiseControl.NET Configuration File");
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.picBrowse_Click);
            // 
            // lblOpen
            // 
            this.lblOpen.AutoSize = true;
            this.lblOpen.Location = new System.Drawing.Point(579, 53);
            this.lblOpen.Name = "lblOpen";
            this.lblOpen.Size = new System.Drawing.Size(0, 13);
            this.lblOpen.TabIndex = 19;
            // 
            // tollTip
            // 
            this.tollTip.IsBalloon = true;
            // 
            // grpDetails
            // 
            this.grpDetails.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.grpDetails.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
            this.grpDetails.Controls.Add(this.lnkExport);
            this.grpDetails.Controls.Add(this.rtbOutput);
            this.grpDetails.Controls.Add(this.lblProgress);
            this.grpDetails.Controls.Add(this.treeStatistics);
            this.grpDetails.Controls.Add(this.lblStats);
            this.grpDetails.ForeColor = System.Drawing.Color.Black;
            this.grpDetails.Location = new System.Drawing.Point(15, 216);
            this.grpDetails.Name = "grpDetails";
            this.grpDetails.Size = new System.Drawing.Size(752, 267);
            this.grpDetails.TabIndex = 20;
            this.grpDetails.TabStop = false;
            this.grpDetails.Text = "Details";
            this.tollTip.SetToolTip(this.grpDetails, "This area displays the details of the processing index rebuild");
            this.grpDetails.Enter += new System.EventHandler(this.grpDetails_Enter);
            // 
            // lnkExport
            // 
            this.lnkExport.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.lnkExport.AutoSize = true;
            this.lnkExport.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.lnkExport.Location = new System.Drawing.Point(684, 28);
            this.lnkExport.Name = "lnkExport";
            this.lnkExport.Size = new System.Drawing.Size(50, 13);
            this.lnkExport.TabIndex = 18;
            this.lnkExport.TabStop = true;
            this.lnkExport.Text = "Export";
            this.lnkExport.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lnkExport_LinkClicked);
            // 
            // groupBox1
            // 
            this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.groupBox1.Controls.Add(this.txtCCNetPath);
            this.groupBox1.Controls.Add(this.lblCCNetConfigPath);
            this.groupBox1.Controls.Add(this.button1);
            this.groupBox1.Controls.Add(this.lstProjects);
            this.groupBox1.Controls.Add(this.btnSelectNone);
            this.groupBox1.Controls.Add(this.btnSelectAll);
            this.groupBox1.Controls.Add(this.btnRecalculateStatistics);
            this.groupBox1.Controls.Add(this.chkDetailedProgress);
            this.groupBox1.Controls.Add(this.lblSelectProjects);
            this.groupBox1.ForeColor = System.Drawing.Color.Black;
            this.groupBox1.Location = new System.Drawing.Point(15, 12);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(752, 199);
            this.groupBox1.TabIndex = 21;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "CCStaistics Input";
            this.groupBox1.Enter += new System.EventHandler(this.groupBox1_Enter);
            // 
            // btnSelectNone
            // 
            this.btnSelectNone.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
            this.btnSelectNone.BackColor = System.Drawing.Color.SteelBlue;
            this.btnSelectNone.FlatAppearance.BorderColor = System.Drawing.Color.Black;
            this.btnSelectNone.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
            this.btnSelectNone.Font = new System.Drawing.Font("Verdana", 8F);
            this.btnSelectNone.ForeColor = System.Drawing.Color.White;
            this.btnSelectNone.Location = new System.Drawing.Point(203, 135);
            this.btnSelectNone.Name = "btnSelectNone";
            this.btnSelectNone.Size = new System.Drawing.Size(89, 24);
            this.btnSelectNone.TabIndex = 5;
            this.btnSelectNone.Text = "Select &None";
            this.btnSelectNone.UseVisualStyleBackColor = false;
            this.btnSelectNone.Click += new System.EventHandler(this.btnSelectNone_Click);
            // 
            // btnSelectAll
            // 
            this.btnSelectAll.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
            this.btnSelectAll.BackColor = System.Drawing.Color.SteelBlue;
            this.btnSelectAll.FlatAppearance.BorderColor = System.Drawing.Color.Black;
            this.btnSelectAll.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
            this.btnSelectAll.Font = new System.Drawing.Font("Verdana", 8F);
            this.btnSelectAll.ForeColor = System.Drawing.Color.White;
            this.btnSelectAll.Location = new System.Drawing.Point(108, 135);
            this.btnSelectAll.Name = "btnSelectAll";
            this.btnSelectAll.Size = new System.Drawing.Size(89, 24);
            this.btnSelectAll.TabIndex = 5;
            this.btnSelectAll.Text = "Select &All";
            this.btnSelectAll.UseVisualStyleBackColor = false;
            this.btnSelectAll.Click += new System.EventHandler(this.btnSelectAll_Click);
            // 
            // progressBar
            // 
            this.progressBar.Dock = System.Windows.Forms.DockStyle.Bottom;
            this.progressBar.Location = new System.Drawing.Point(0, 517);
            this.progressBar.Name = "progressBar";
            this.progressBar.Size = new System.Drawing.Size(779, 22);
            this.progressBar.Step = 1;
            this.progressBar.TabIndex = 13;
            // 
            // MainForm
            // 
            this.AllowDrop = true;
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
            this.BackColor = System.Drawing.Color.DarkGray;
            this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
            this.ClientSize = new System.Drawing.Size(779, 539);
            this.Controls.Add(this.groupBox1);
            this.Controls.Add(this.grpDetails);
            this.Controls.Add(this.lblOpen);
            this.Controls.Add(this.progressBar);
            this.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.ForeColor = System.Drawing.Color.White;
            this.HelpButton = true;
            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
            this.Menu = this.mainMenu;
            this.MinimumSize = new System.Drawing.Size(588, 500);
            this.Name = "MainForm";
            this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
            this.Text = "CCStatistics";
            this.Load += new System.EventHandler(this.MainForm_Load);
            this.grpDetails.ResumeLayout(false);
            this.grpDetails.PerformLayout();
            this.groupBox1.ResumeLayout(false);
            this.groupBox1.PerformLayout();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion Windows Form Designer generated code

        #region Protected Methods

        /// <summary>
        /// Override the Load event for initialisation.
        /// </summary>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (!DesignMode)
            {
                // Wire in unhandled exceptions to be displayed via event handler below.
                Application.ThreadException += _OnThreadExceptionHandler;
                AppDomain.CurrentDomain.UnhandledException += _OnCurrentDomainUnhandledExceptionHandler;

                // We need to make sure this assembly is loaded in memory otherwise NetReflector barfs
                // when parsing configuration files with <externalLink> elements.

                ////////////////////////////////////////////////////////////////////////////////////////
                // Damon Carr --> Query 
                // No longer necessary perhaps as this is set as a project reference.. 
                // As the app is dependent on these assemblies we might as well distribute them
                // as this makes it far simpler to distribute, install and upgrade.
                //Assembly.Load("ThoughtWorks.ruiseControl.Remote");
                /////////////////////////////////////////////////////////////////////////////////////////
                // Figure out the location of the ccnet.config file
                // Want people to be running this from the CC.Net server folder - but could be in debug mode from the IDE.
                //////////////////////////////////////////////////////////////////////////////////////////
                /// Minor Refactoring for running in production
                /// Damon Carr 7/28/2007
                //////////////////////////////////////////////////////////////////////////////////////////
                //if (startupCCConfigPath.EndsWith("Debug"))
                //startupCCConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), ccnetServerDir);
                //txtCCNetPath.Text = Path.Combine(startupFolder, "ccnet.config");

                txtCCNetPath.Text = ProjectStatisticsPresenter.GetCCConfigPath(Application.StartupPath);
            }
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
                if (components != null)
                    components.Dispose();
            base.Dispose(disposing);
        }

        #endregion Protected Methods

        #region ICCStatsView Members

        public void UpdateViewFromActiveStatistics(List<Statistic> statistics, string projectName)
        {
            var iIndex = 0;
            var iProjVal = AddRoot(projectName);
            statistics.ForEach(x =>
                AddStatNode("node" + (iIndex++), x.Name + " [" + x.Xpath + "]", iProjVal));

            treeStatistics.ExpandAll();

        }

        public DateTime RenderProjectStart(string name, DateTime dtIn)
        {
            WriteLine("--------------------------------------------------");
            WriteLine("Project: " + Name);
            WriteLine("--------------------------------------------------");

            return dtIn;
        }

        public void Clear()
        {
            rtbOutput.Clear();
        }

        public void WriteDetailLine(string message)
        {
            if (chkDetailedProgress.Checked)
                WriteLine(message);
        }

        public void WriteLine(string message)
        {
            rtbOutput.AppendText(message + "\n");
            // Scroll down a line
            NativeMethods.SendMessage(rtbOutput.Handle, WM_VSCROLL, (IntPtr)SB_LINEDOWN, (IntPtr)0);
            Application.DoEvents();
        }

        public void InitialiseProgress(int totalLogFiles)
        {
            progressBar.Minimum = 0;
            progressBar.Maximum = totalLogFiles;
            progressBar.Value = 0;
            progressBar.Refresh();
        }

        public void IncrementProgress()
        {
            progressBar.Increment(1);
            progressBar.Refresh();
            Thread.Sleep(10);
        }

        public void AlertBatch(IEnumerator<string> alertMessage)
        {
            while (alertMessage.MoveNext())
                WriteLine(alertMessage.Current);

            var result = MessageBox.Show(this,
                                         "Log files are displayed. Would you like to continue?",
                                         "Information Message",
                                         MessageBoxButtons.YesNo,
                                         MessageBoxIcon.Question,
                                         MessageBoxDefaultButton.Button1);

            if (result != DialogResult.Yes)
                CloseApplication();
        }

        public void Alert(string message)
        {
            MessageBox.Show(this, message, Application.ProductName, MessageBoxButtons.OK);
        }

        public void EndExecutionRun(string projectName, bool cancelAbort)
        {
            WriteLine("--------------------------------------------------");
            if (cancelAbort)
            {
                WriteLine("Canceled by User. Processing Aborted.");
                _lastProjectWasAborted = true;
            }
            else
                WriteLine(string.Format(" Project '{0}' Complete", projectName));

            WriteLine("--------------------------------------------------");
        }

        #endregion

        private void _OnFileExitMenuClick(object sender, EventArgs e)
        {
            Close();
        }

        private void _OnHelpAboutClick(object sender, EventArgs e)
        {
            new About().ShowDialog();
        }

        private void loadCCNetConfigFile()
        {
            var configFileName = txtCCNetPath.Text;
            IConfiguration configuration;

            if (!File.Exists(configFileName))
                ShowOKAlert("Unable to find the file specified. Please try again");
            else
            {
                var configFileInfo = new FileInfo(configFileName);
                try
                {
                    configuration = ProjectStatisticsPresenter.LoadCCNetConfigFile(configFileInfo);
                }                    
                catch (Exception ex) // Not sure of the CC Exception Type.. TO DO: Find and change overly generic here
                //   specific type is ThoughtWorks.CruiseControl.Core.Config.ConfigurationException - but given 
                //    the number of 'unknown unknowns' that exist here, actually prefer the generic type for now...
                {
                    ShowOKAlert(
                        "An error occured loading the configuration file. The error from CruiseControl.NET was: "
                        + ex.Message);
                    return;
                }

                PopulateProjectsList(configuration.Projects);

                // Get the base directory for CC.Net and set the environment to be that to ensure any
                // relative paths for the project are calculated as though being run from CC.Net.
                if (configFileInfo.DirectoryName != null)
                    Environment.CurrentDirectory = configFileInfo.DirectoryName;
                else
                    throw new InvalidOperationException("No directory set for current");
            }
        }

        private static void ShowOKAlert(String message)
        {
            MessageBox.Show(message, "Alert", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }

        private void _OnRecalculateStatisticsButtonClick(object sender, EventArgs e)
        {
            if (lstProjects.CheckedItems.Count > 0)
            {
                Cursor = Cursors.WaitCursor;
                Clear();
                WriteLine("*** Starting Recalculations ***");
                prepScreenForThreadExec(true);
                setInitialTreeViewState();

                // NOTE: New thread to come....
                StartMainBackgroundThreadLoop();

                Cursor = DefaultCursor;
            }
        }

        private void setInitialTreeViewState()
        {
            if (!chkDetailedProgress.Visible)
                return;
            treeStatistics.Nodes.Clear();
            treeStatistics.Visible = true;
            lblStats.Visible = true;
        }

        private void prepScreenForThreadExec(bool threadStart)
        {
            btnRecalculateStatistics.Enabled = !threadStart;
            lstProjects.Enabled = !threadStart;
            btnSelectNone.Enabled = !threadStart;
            btnSelectAll.Enabled = !threadStart;
        }

        private void StartMainBackgroundThreadLoop()
        {
            _lastProjectWasAborted = false;
            ProjectStatisticsPresenter _ProjectStatisticsPresenter;
            var startTime = DateTime.Now;

            foreach (string projectName in lstProjects.CheckedItems)
            {
                WriteLine(@"Starting Project " + projectName);
                var currentProject = _projects[projectName];
                if (currentProject == null)
                {
                    WriteLine(" Cannot Recalculate Statistics for project " + projectName);
                    continue;
                }
                var statsPublisherForProject = getStatsPublisher(currentProject);
                if (statsPublisherForProject == null)
                {
                    WriteLine(" Failed to obtain the StatisticsPublisher for project " + projectName);
                    continue;
                }

                var buildLogDir = getBuildLogDirectory(currentProject);

                if (!Directory.Exists(buildLogDir))
                {
                    WriteLine(string.Format(" Log file directory '{0}' for project '{1}' does not exist.  It may have never yet been built, or you may not have permissions to read it.", buildLogDir, projectName));
                    WriteLine(" Skipping project " + projectName);
                    continue;
                    
                }
                _ProjectStatisticsPresenter = new ProjectStatisticsPresenter(this,
                                                                             currentProject,
                                                                             statsPublisherForProject,
                                                                             buildLogDir);
                _ProjectStatisticsPresenter.RecalculateStatistics();

                if (_lastProjectWasAborted)
                    break;
            }

            WriteLine(string.Format("*** All projects Completed ***"));

            var endTime = DateTime.Now;
            var elapsedTime = endTime.Subtract(startTime);
            WriteLine("*** Ended at: " + startTime + " - Time taken: " + elapsedTime);

            Cursor = Cursors.Default;
            prepScreenForThreadExec(false);

        }

        private static string getBuildLogDirectory(IProject currentProject)
        {
            if (currentProject == null)
                throw new ArgumentNullException("currentProject");

            var ArtifactDirectory = ((Project)currentProject).ArtifactDirectory;

            if (String.IsNullOrEmpty(ArtifactDirectory))
                throw new InvalidOperationException("The artifact Directory is Undefined");

            var pub = GetTypeInstanceFromPublishers(currentProject, typeof(XmlLogPublisher));
            return ((XmlLogPublisher)pub).LogDirectory(ArtifactDirectory); // ConfiguredLogDirectory;
        }

        private static ITask GetTypeInstanceFromPublishers(IProject currentProject, Type targetType)
        {
            return Array.Find(((Project)currentProject).Publishers, checkVal => checkVal.GetType().Equals(targetType));
        }

        private static bool hasStatsPublisher(IProject currentProject)
        {
            var pub = GetTypeInstanceFromPublishers(currentProject, typeof (StatisticsPublisher));
            return pub != null;
        }

        private static ICCStatisticsPublisher getStatsPublisher(IProject currentProject)
        {
            var pub = GetTypeInstanceFromPublishers(currentProject, typeof(StatisticsPublisher));
            return pub == null ? null : new CCStatisticsPublisher(((StatisticsPublisher)pub).ConfiguredStatistics);
        }

        private int AddRoot(String ProjectName)
        {
            var oProjectRoot = new TreeNode(ProjectName, 0, 0);
            oProjectRoot.ExpandAll();
            return treeStatistics.Nodes.Add(oProjectRoot);
        }

        private void AddStatNode(String Key, String NodeDisplay, int iParentNode)
        {
            treeStatistics.Nodes[iParentNode].Nodes.Add(Key, NodeDisplay, 1, 1);
        }

        private void PopulateProjectsList(IProjectList projects)
        {
            _projects = projects;

            lstProjects.Items.Clear();

            foreach (IProject project in projects)
            {
                if (hasStatsPublisher(project))
                    lstProjects.Items.Add(project.Name);
                else
                    // add a suffix to the name that prevents selection for includsion, and explains why
                    lstProjects.Items.Add(project.Name + " - StatisticsPublisher not enabled for this project");
            }

            lstProjects.Sorted = true;
        }

        private void lstProjects_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            var listItemText = (string)lstProjects.Items[e.Index];

            //if the list item text does not match the project name, we assume it cannot be validly selected
            var currentProject = _projects[listItemText];

            if (currentProject == null && e.NewValue == CheckState.Checked)
                e.NewValue = e.CurrentValue;
        }

        /// <summary>
        /// Event handler to pickup unhandled exceptions and display in a message box.
        /// </summary>
        private void _OnThreadExceptionHandler(object sender, ThreadExceptionEventArgs e)
        {
            _HandleException(e.Exception);
        }

        /// <summary>
        /// Event handler to pickup unhandled exceptions and display in a message box.
        /// </summary>
        private void _OnCurrentDomainUnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs e)
        {
            _HandleException(e.ExceptionObject as Exception);
        }

        private void _HandleException(Exception ex)
        {
            MessageBox.Show(ex + Environment.NewLine + Environment.NewLine + "Application will now exit.",
                            Application.ProductName,
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Error);

            try
            {
                Close();
            }
            catch (Exception failFastEx)
            {
                Environment.FailFast(failFastEx.GetBaseException().Message);
            }
        }

        private void CloseApplication()
        {
            try
            {
                _projects = null;
                Close();
            }
            catch
            {
                Environment.FailFast("Unable to gracefully close CCStatistics. Performing FailFast");
            }
        }

        private void picBrowse_Click(object sender, EventArgs e)
        {
            dlgCCNetOPenConfig.InitialDirectory = txtCCNetPath.Text;

            if (dlgCCNetOPenConfig.ShowDialog() != DialogResult.OK)
                return;

            txtCCNetPath.Text = dlgCCNetOPenConfig.FileName;
            loadCCNetConfigFile();
        }

        private void rtbOutput_TextChanged(object sender, EventArgs e) { }

        private void MainForm_Load(object sender, EventArgs e)
        {
            Text += " " + Assembly.GetExecutingAssembly().GetName().Version;
        }

        private void lblStats_Click(object sender, EventArgs e) { }

        private void chkDetailedProgress_CheckedChanged(object sender, EventArgs e)
        {
            grpDetails.Visible = chkDetailedProgress.Checked;

            Height = (Convert.ToInt16(grpDetails.Visible) * 200) + 300;

            progressBar.Visible = grpDetails.Visible;
        }

        private void grpDetails_Enter(object sender, EventArgs e) { }

        private void lnkExport_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (String.IsNullOrEmpty(rtbOutput.Text))
                return;

            var strNewFile = ExportFile(rtbOutput.Text);

            saveFileDialog1.FileName = strNewFile;
            saveFileDialog1.OpenFile();
            saveFileDialog1.FileName = "ccstatistics";
            saveFileDialog1.DefaultExt = "txt";
            saveFileDialog1.RestoreDirectory = true;
            saveFileDialog1.OverwritePrompt = true;
            saveFileDialog1.CreatePrompt = true;
            saveFileDialog1.ShowDialog();
        }

        private static String ExportFile(string text)
        {
            var strFileName = Environment.GetEnvironmentVariable("TEMP") + Guid.NewGuid().ToString().Replace("-", "")
                              + ".txt";
            var newFile = File.CreateText(strFileName);
            newFile.Write(text);
            newFile.Close();
            return strFileName;
        }

        private void groupBox1_Enter(object sender, EventArgs e) { }

       
        private void btnSelectAll_Click(object sender, EventArgs e)
        {
            setIsCheckedForAllItems(lstProjects, true);
        }

        private void btnSelectNone_Click(object sender, EventArgs e)
        {
            setIsCheckedForAllItems(lstProjects, false);
        }

        private static void setIsCheckedForAllItems(CheckedListBox listBox, bool isChecked)
        {
            for (var i = 0; i < listBox.Items.Count; i++)
            {
                listBox.SetItemChecked(i, isChecked);
            }
        }
    }
}